home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
windows
/
ats113.zip
/
REXEC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-14
|
20KB
|
858 lines
/*
* Copyright (c) 1994-1996 Ataman Software, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Ataman Software, Inc.
* 4. The name of Ataman Software, Inc. may not may be used to endorse or
* promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY ATAMAN SOFTWARE, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ATAMAN SOFTWARE, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
static char copyright[] =
"Copyright (c) 1994-1996 Ataman Software, Inc. All rights reserved.";
/*
* To compile this program for use under Windows NT or Windows 95 using
* Microsoft Visual C++, rename the file rexec.c to rexec.cpp and then
* use the following command:
* cl -DWIN32 -O2 -D_MT /MT rexec.cpp libcmt.lib kernel32.lib advapi32.lib wsock32.lib
*/
#ifdef WIN32
#pragma warning(disable: 4699)
/* Includes for Win32 systems go here. */
#define STRICT
#pragma warning(disable: 4201)
#include <windows.h>
#pragma warning(default: 4201)
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <signal.h>
#define RETVAL DWORD
#define IDENT HANDLE
#define STDINPUT hStdIn
#define STDOUTPUT hStdOut
#define STDERROR hStdErr
#define FILECOOKIE HANDLE
static void PassInputThread(void *);
static void PassOutputThread(void *);
static void PassErrorThread(void *);
HANDLE hStdIn, hStdOut, hStdErr;
#else
/* Includes for Unix systems go here. */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sgtty.h>
#define SOCKET int
#define RETVAL int
#define IDENT int
#define INVALID_SOCKET (-1)
#define SOCKET_ERROR (-1)
#define WSAGetLastError() errno
#define GetLastError() ((unsigned long)errno)
#define closesocket(s) close(s)
#define STDINPUT 0
#define STDOUTPUT 1
#define STDERROR 2
#define FILECOOKIE int
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif
/*
Think carefully before enabling the -p option. While it may be
convenient to have this option, it is for many (if not most) sites a
security hole. Remember that the '-p password' used on the command
line is visible on most Unix systems to any user that is allow to run
the 'ps' command (normally ALL users can run this command). While no
utility that comes by default with Windows NT at this time, shows the
same information, it is unclear whether or not the information is
avaiable to all users. Certainly privileged users would be be able to
see this information on any system.
If the security risk is acceptable at your site, you can enable the -p
option by uncommenting the #define below.
*/
/* #define ALLOWDASH_P */
static void Usage(void);
static int NullStdIn;
static char *GetUsername(void);
static char *GetPassword(void);
static void OpenService(const char *remote_host);
static void Cleanup(void);
static IDENT PassInput(void);
static IDENT PassOutput(void);
static IDENT PassError(void);
static BOOL Close(FILECOOKIE);
static int Read(FILECOOKIE, char *, size_t);
static BOOL Write(FILECOOKIE, const char *, size_t);
static BOOL Send(SOCKET, const char *, size_t);
static BOOL SendZString(const char *);
static BOOL GetErrString(char *, size_t);
static void Wait(IDENT, RETVAL *);
static SOCKET sIO = INVALID_SOCKET;
static SOCKET sErr = INVALID_SOCKET;
IDENT idIn = 0;
IDENT idOut, idErr;
void main(int argc, char *argv[])
{
char *hostname;
char *username;
char *password;
char command[4096];
size_t cmdlen;
int i;
RETVAL rvIn, rvOut, rvErr;
if (argc < 3) {
Usage();
}
#ifdef WIN32
hStdIn = GetStdHandle(STD_INPUT_HANDLE);
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
hStdErr = GetStdHandle(STD_ERROR_HANDLE);
#endif
hostname = argv[1];
password = NULL;
username = NULL;
for (i=2; i<argc; i++) {
if (*argv[i] != '-') {
break;
} else if (strcmp(argv[i], "--") == 0) {
i++;
break;
} else if (strcmp(argv[i], "-n") == 0) {
NullStdIn = 1;
} else if (strcmp(argv[i], "-l") == 0) {
username = argv[++i];
} else if (strcmp(argv[i], "-p") == 0) {
#ifdef ALLOWDASH_P
password = argv[++i];
#else
fprintf(stderr,
"The -p option is a potential security hole, "
"please see the comments in the source code\n"
"before enabling this feature.\n");
exit(1);
#endif
} else {
Usage();
}
}
if (i >= argc) {
Usage();
}
*command = '\0';
cmdlen = 0;
for (; i<argc; i++) {
size_t arglen;
arglen = strlen(argv[i]);
if (cmdlen+arglen+2 > sizeof command) {
fprintf(stderr, "Command too long.\n");
exit(1);
}
strcpy(&command[cmdlen], argv[i]);
strcpy(&command[cmdlen+arglen], " ");
cmdlen += arglen+1;
}
if (!username) {
username = GetUsername();
}
if (!password) {
password = GetPassword();
}
OpenService(hostname);
SendZString(username);
SendZString(password);
memset (password, '\0', strlen(password));
SendZString(command);
if (!GetErrString(command, sizeof command)) {
fprintf(stderr, "Remote aborted connection without initiating protocol: %d.\n",
WSAGetLastError());
exit(1);
}
if (*command != '\0') {
char *p = command;
if (*p == '\001') {
p++;
}
fprintf(stderr, "Remote aborted connection: %s\n", p);
exit(1);
}
if (!NullStdIn) {
idIn = PassInput();
} else {
if (!Close(STDINPUT)) {
fprintf(stderr, "Failed to close standard input: error = %lu.\n",
GetLastError());
exit(1);
}
if (shutdown(sIO, 1) == SOCKET_ERROR) {
fprintf(stderr, "Failed to shutdown from input socket: error = %d.\n",
WSAGetLastError());
exit(1);
}
}
idOut = PassOutput();
idErr = PassError();
if (!NullStdIn) {
Wait(idIn, &rvIn);
} else {
rvIn = 0;
}
Wait(idOut, &rvOut);
Wait(idErr, &rvErr);
exit((int)(rvIn | rvOut | rvErr));
}
static char *GetUsername()
{
static char username[1024];
#ifdef WIN32
unsigned char tubuf[1024];
char chDomain[510];
TOKEN_USER *ptu = (TOKEN_USER *)tubuf;
SID_NAME_USE snu;
DWORD cbUser, cbDomain, cbDummy;
HANDLE hAccessToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken)) {
fprintf(stderr, "Can't open process token: error = %lu.\n", GetLastError());
exit(1);
}
if (!GetTokenInformation(hAccessToken, TokenUser, ptu, sizeof tubuf, &cbDummy)) {
fprintf(stderr, "Can't get user sid: error = %lu.\n", GetLastError());
exit(1);
}
cbUser = sizeof username;
cbDomain = sizeof chDomain;
if (!LookupAccountSid(NULL, ptu->User.Sid, username, &cbUser, chDomain, &cbDomain, &snu)) {
fprintf(stderr,